package com.woniu.cms.goods.core.service.impl;

import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.conditions.update.LambdaUpdateWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.core.toolkit.ObjectUtils;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.woniu.cms.goods.core.entity.GoodsGetbill;
import com.woniu.cms.goods.core.entity.GoodsGetbillMaterial;
import com.woniu.cms.goods.core.entity.GoodsMaterial;
import com.woniu.cms.goods.core.exception.Asserts;
import com.woniu.cms.goods.core.exception.BusinessException;
import com.woniu.cms.goods.core.mapper.GoodsGetbillMapper;
import com.woniu.cms.goods.core.service.IGoodsGetbillMaterialService;
import com.woniu.cms.goods.core.service.IGoodsGetbillService;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.woniu.cms.goods.core.service.IGoodsMaterialService;
import com.woniu.common.api.Result;
import com.woniu.common.api.status.Impl.BusinessCode;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Isolation;
import org.springframework.transaction.annotation.Propagation;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.web.multipart.MultipartFile;

import java.io.File;
import java.io.IOException;
import java.io.InputStream;
import java.util.List;
import java.util.stream.Collectors;

/**
 * <p>
 * 入库单表 服务实现类
 * </p>
 *
 * @author romantic sheep
 * @since 2022-09-16
 */
@Service
public class GoodsGetbillServiceImpl extends ServiceImpl<GoodsGetbillMapper, GoodsGetbill> implements IGoodsGetbillService {

    @Autowired
    private IGoodsGetbillMaterialService materialService;
    @Autowired
    private GoodsGetbillMapper goodsGetbillMapper;


    @Override
    @Transactional( propagation = Propagation.REQUIRED  //必须添加事务
            ,timeout = -1         //设置连接永不超时
            ,rollbackFor = {BusinessException.class}  // 抛出异常时进行回滚
            ,isolation = Isolation.DEFAULT                   // 使用数据库的隔离级别
    )
    public Result addGetbill(GoodsGetbill getbill, List<GoodsGetbillMaterial> list) {
        if (ObjectUtils.isEmpty(getbill)){
            return Result.error("请输入必填数据");
        }
        RedisTemplate redisTemplate=new RedisTemplate();
        redisTemplate.multi();
        //保存入库单主表，若失败则抛出运行时异常进行事务回滚
        boolean save = this.save(getbill);
        if (!save){
            Asserts.failed("保存失败，事务回滚");
        }
        //查询订单主表主键，存入材料明细表外键
        LambdaQueryWrapper<GoodsGetbill> qw = Wrappers.lambdaQuery();
        qw.eq(GoodsGetbill::getGetbillCode,getbill.getGetbillCode());
        GoodsGetbill getbill1 = this.getOne(qw);
        List<GoodsGetbillMaterial> collect = list.stream().map(e -> {
            e.setGetbillId(getbill1.getId());
            return e;
        }).collect(Collectors.toList());
        //保存材料明细表，若失败则抛出运行时异常进行事务回滚
        boolean b = materialService.saveBatch(collect);
        if (!b){
            Asserts.failed("保存失败，事务回滚");
        }
        return Result.ok(BusinessCode.ADD_SUCCESS);
    }

    @Override
    @Transactional( propagation = Propagation.REQUIRED  //必须添加事务
            ,timeout = -1         //设置连接永不超时
            ,rollbackFor = {BusinessException.class}  // 抛出异常时进行回滚
            ,isolation = Isolation.DEFAULT                   // 使用数据库的隔离级别
    )
    public Result deleteGetbill(Integer id, Integer status) {
        GoodsGetbill goodsGetbill = this.getById(id);
        if (ObjectUtils.isEmpty(goodsGetbill)){
            return Result.error(BusinessCode.REMOVE_FAIL);
        }
        if (goodsGetbill.getStatus()!=0&&goodsGetbill.getStatus()!=3){
            Asserts.failed("单据已提交无法删除");
        }
        boolean b = this.removeById(id);
        if (!b){
            Asserts.failed("删除失败,事务回滚");
        }
        LambdaUpdateWrapper<GoodsGetbillMaterial> updateWrapper = Wrappers.lambdaUpdate();
        updateWrapper.eq(GoodsGetbillMaterial::getGoodsCode,goodsGetbill.getGetbillCode());
        boolean remove = materialService.remove(updateWrapper);
        if (!remove){
            Asserts.failed("删除失败,事务回滚");
        }
        //需要事务控制材料删除失败则回滚
        return Result.ok(BusinessCode.REMOVE_SUCCESS);
    }

    @Override
    @Transactional( propagation = Propagation.REQUIRED  //必须添加事务
            ,timeout = -1         //设置连接永不超时
            ,rollbackFor = {BusinessException.class}  // 抛出异常时进行回滚
            ,isolation = Isolation.DEFAULT                   // 使用数据库的隔离级别
    )
    public Result updateGetbill(GoodsGetbill getbill, List<GoodsGetbillMaterial> list) {
        if (getbill.getStatus()!=0&&getbill.getStatus()!=3){
            return Result.error(BusinessCode.MODIFY_FAIL);
        }
        boolean b = this.updateById(getbill);
        if (!b){
            Asserts.failed("修改失败,事务回滚");
        }
        //事务控制。若修改失败则回滚
        boolean b1 = materialService.updateBatchById(list);
        if (!b1){
            Asserts.failed("修改失败,事务回滚");
        }
        return Result.ok(BusinessCode.MODIFY_SUCCESS);
    }

    @Override
    @Transactional( propagation = Propagation.REQUIRED  //必须添加事务
            ,timeout = -1         //设置连接永不超时
            ,rollbackFor = {BusinessException.class}  // 抛出异常时进行回滚
            ,isolation = Isolation.DEFAULT                   // 使用数据库的隔离级别
    )
    public Result commitGetbill(GoodsGetbill getbill, List<GoodsGetbillMaterial> list) {
        if (getbill.getStatus()==2){
            return Result.error("单据已提交，无法重复提交");
        }
        getbill.setStatus(1);
        boolean b = this.updateById(getbill);
        if (!b){
            Asserts.failed("提交失败,事务回滚");
        }
        List<GoodsGetbillMaterial> collect = list.stream().map(e -> {
            e.setResidueNum(e.getGetbillNum());
            return e;
        }).collect(Collectors.toList());
        boolean b1 = materialService.updateBatchById(collect);
        if (!b1){
            Asserts.failed("提交失败,事务回滚");
        }
        return Result.ok("单据提交成功");

    }

}
